﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.ProgressBar;
using YJKRevitBase.WinForm;

namespace YJKColumnModify.ConnectColumnBream
{
	internal class AnalyzeBream
	{
		public AnalyzeBream(ExternalCommandData commandData, List<BreamInfo> lstBreamInfo)
		{
			this.m_commandData = commandData;
			this.m_uiDoc = commandData.Application.ActiveUIDocument;
			this.m_doc = this.m_uiDoc.Document;
			this.m_lstBreamInfo = lstBreamInfo;
		}

		public Dictionary<string, List<ConnectColumnBreamInfo>> GetConnectColumnBreams()
		{
			Dictionary<string, List<ConnectColumnBreamInfo>> dictionary = new Dictionary<string, List<ConnectColumnBreamInfo>>();
			foreach (ConnectColumnBreamInfo connectColumnBreamInfo in this.GetConnectColumnBream())
			{
				string title = connectColumnBreamInfo.ConnectBreamInfo.BreamViewPlan.Title;
				if (dictionary.ContainsKey(title))
				{
					dictionary[title].Add(connectColumnBreamInfo);
				}
				else
				{
					dictionary.Add(title, new List<ConnectColumnBreamInfo>
					{
						connectColumnBreamInfo
					});
				}
			}
			return dictionary;
		}

		public List<ConnectColumnBreamInfo> GetConnectColumnBream()
		{
			WindowHandle owner = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			List<ConnectColumnBreamInfo> list = new List<ConnectColumnBreamInfo>();
			using (ProgressBarForm progressBarForm = new ProgressBarForm(this.m_lstBreamInfo.Count, ProgressBarStyle.Blocks, true))
			{
				progressBarForm.Show(owner);
				foreach (BreamInfo breamInfo in this.m_lstBreamInfo)
				{
					try
					{
						List<FamilyInstance> list2 = new List<FamilyInstance>();
						this.GetBreamOldColumn(ref list2, breamInfo.Bream);
						foreach (FamilyInstance familyInstance in list2)
						{
							XYZ connectPoint = this.GetConnectPoint(breamInfo.Bream, familyInstance);
							ConnectColumnBreamInfo connectColumnBreamInfo = ConnectColumnBreamInfo.CreateConnectColumnBreamInfo(this.m_commandData, breamInfo, connectPoint, familyInstance);
							if (connectColumnBreamInfo != null)
							{
								list.Add(connectColumnBreamInfo);
							}
						}
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							break;
						}
					}
					catch
					{
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							break;
						}
					}
				}
			}
			return list;
		}

		private void GetBreamOldColumn(ref List<FamilyInstance> lstColumn, FamilyInstance bream)
		{
			double breamThickness = this.GetBreamThickness(bream);
			IList<CurveLoop> list = new List<CurveLoop>();
			CurveLoop item = this.GetBreamOutLine(bream);
			list.Add(item);
			List<Element> lstTwo = new List<Element>();
			Solid tagSolid = null;
			try
			{
				tagSolid = GeometryCreationUtilities.CreateExtrusionGeometry(list, -XYZ.BasisZ, breamThickness);
			}
			catch
			{
			}
			lstTwo = Collider.GetElementByCollision(tagSolid, (BuiltInCategory)(-2001330), this.m_doc);
			list.Clear();
			item = this.GetTempBreamOutLine(bream);
			list.Add(item);
			tagSolid = GeometryCreationUtilities.CreateExtrusionGeometry(list, -XYZ.BasisZ, breamThickness);
			List<Element> lstOne = new List<Element>();
			lstOne = Collider.GetElementByCollision(tagSolid, (BuiltInCategory)(-2001330), this.m_doc);
			list.Clear();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			foreach (Element element in this.GetNoEqualElement(lstOne, lstTwo))
			{
				list2.Add(element as FamilyInstance);
			}
			lstColumn = list2;
		}

		private CurveLoop GetBreamOutLine(FamilyInstance bream)
		{
			Curve curve = (bream.Location as LocationCurve).Curve;
			CurveLoop curveLoop = new CurveLoop();
			XYZ xyz = this.GetVerticalSide(bream) / 2.0;
			XYZ xyz2 = -xyz;
			XYZ xyz3 = curve.GetEndPoint(0) + xyz;
			XYZ xyz4 = curve.GetEndPoint(1) + xyz;
			XYZ xyz5 = curve.GetEndPoint(1) + xyz2;
			XYZ xyz6 = curve.GetEndPoint(0) + xyz2;
			double num = 0.0;
			Parameter parameter = bream.get_Parameter(BuiltInParameter.Z_OFFSET_VALUE);
			if (parameter != null)
			{
				num = parameter.AsDouble();
			}
			xyz3 = new XYZ(xyz3.X, xyz3.Y, xyz3.Z + num);
			xyz4 = new XYZ(xyz4.X, xyz4.Y, xyz4.Z + num);
			xyz5 = new XYZ(xyz5.X, xyz5.Y, xyz5.Z + num);
			xyz6 = new XYZ(xyz6.X, xyz6.Y, xyz6.Z + num);
			Line line = Line.CreateBound(xyz3, xyz4);
			Line line2 = Line.CreateBound(xyz4, xyz5);
			Line line3 = Line.CreateBound(xyz5, xyz6);
			Line line4 = Line.CreateBound(xyz6, xyz3);
			curveLoop.Append(line);
			curveLoop.Append(line2);
			curveLoop.Append(line3);
			curveLoop.Append(line4);
			return curveLoop;
		}

		private CurveLoop GetTempBreamOutLine(FamilyInstance bream)
		{
			Curve curve = (bream.Location as LocationCurve).Curve;
			XYZ xyz = curve.GetEndPoint(1) - curve.GetEndPoint(0);
			double length = xyz.GetLength();
			double num = 201.0 * BreamConnectColumnGeometryToos.OneMillimeter / length;
			XYZ xyz2 = xyz + xyz * num + curve.GetEndPoint(0);
			XYZ xyz3 = -(xyz * num) + curve.GetEndPoint(0);
			CurveLoop curveLoop = new CurveLoop();
			XYZ xyz4 = this.GetVerticalSide(bream) / 2.0;
			XYZ xyz5 = -xyz4;
			XYZ xyz6 = xyz2 + xyz4;
			XYZ xyz7 = xyz3 + xyz4;
			XYZ xyz8 = xyz3 + xyz5;
			XYZ xyz9 = xyz2 + xyz5;
			double num2 = 0.0;
			Parameter parameter = bream.get_Parameter(BuiltInParameter.Z_OFFSET_VALUE);
			if (parameter != null)
			{
				num2 = parameter.AsDouble();
			}
			xyz6 = new XYZ(xyz6.X, xyz6.Y, xyz6.Z + num2);
			xyz7 = new XYZ(xyz7.X, xyz7.Y, xyz7.Z + num2);
			xyz8 = new XYZ(xyz8.X, xyz8.Y, xyz8.Z + num2);
			xyz9 = new XYZ(xyz9.X, xyz9.Y, xyz9.Z + num2);
			Line line = Line.CreateBound(xyz6, xyz7);
			Line line2 = Line.CreateBound(xyz7, xyz8);
			Line line3 = Line.CreateBound(xyz8, xyz9);
			Line line4 = Line.CreateBound(xyz9, xyz6);
			curveLoop.Append(line);
			curveLoop.Append(line2);
			curveLoop.Append(line3);
			curveLoop.Append(line4);
			return curveLoop;
		}

		private XYZ GetVerticalSide(FamilyInstance bream)
		{
			Curve curve = (bream.Location as LocationCurve).Curve;
			Transform transform = bream.GetTransform();
            Solid famliySymbolSolid = BreamConnectColumnGeometryToos.GetFamliySymbolSolid(bream.Symbol, (ViewDetailLevel)2);
			XYZ xyz = curve.GetEndPoint(1) - curve.GetEndPoint(0);
			try
			{
				xyz = new XYZ(xyz.X / xyz.GetLength(), xyz.Y / xyz.GetLength(), xyz.Z / xyz.GetLength());
			}
			catch
			{
			}
			XYZ result = null;
			double num = 0.0;
			foreach (object obj in famliySymbolSolid.Edges)
			{
				Edge edge = (Edge)obj;
				double approximateLength = edge.ApproximateLength;
				Curve curve2 = edge.AsCurve();
				XYZ xyz2 = transform.OfPoint(curve2.GetEndPoint(1)) - transform.OfPoint(curve2.GetEndPoint(0));
				xyz2 = new XYZ(xyz2.X / xyz2.GetLength(), xyz2.Y / xyz2.GetLength(), xyz2.Z / xyz2.GetLength());
				if (!xyz2.IsAlmostEqualTo(XYZ.BasisZ) && !xyz2.IsAlmostEqualTo(-XYZ.BasisZ) && Math.Abs(xyz2.DotProduct(xyz)) <= 0.005 && approximateLength >= num)
				{
					num = approximateLength;
					result = xyz2;
				}
			}
			return result;
		}

		private double GetBreamThickness(FamilyInstance bream)
		{
            Solid famliySymbolSolid = BreamConnectColumnGeometryToos.GetFamliySymbolSolid(bream.Symbol, (ViewDetailLevel)2);
			List<Line> list = new List<Line>();
			Curve curve = (bream.Location as LocationCurve).Curve;
			BreamConnectColumnGeometryToos.GetLineToSolid(famliySymbolSolid, bream.GetTransform(), curve, XYZ.BasisZ, Math.PI*.5, ref list);
			list = (from r in list
			orderby r.Length descending
			select r).ToList<Line>();
			Line template = list[0];
			List<Line> source = new List<Line>();
			XYZ normal = curve.GetEndPoint(1) - curve.GetEndPoint(0);
			BreamConnectColumnGeometryToos.GetLineToSolid(famliySymbolSolid, bream.GetTransform(), template, normal, Math.PI*.5, ref source);
			return source.Max((Line r) => r.Length);
		}

		private XYZ GetConnectPoint(FamilyInstance bream, FamilyInstance colunm)
		{
			XYZ xyz = (colunm.Location as LocationPoint).Point;
			if (xyz == null)
			{
				xyz = (colunm.Location as LocationCurve).Curve.GetEndPoint(0);
				if (xyz.Z < (colunm.Location as LocationCurve).Curve.GetEndPoint(1).Z)
				{
					xyz = (colunm.Location as LocationCurve).Curve.GetEndPoint(1);
				}
			}
			XYZ endPoint = (bream.Location as LocationCurve).Curve.GetEndPoint(0);
			XYZ endPoint2 = (bream.Location as LocationCurve).Curve.GetEndPoint(1);
			if (Math.Abs(endPoint.X - endPoint2.X) < 0.065616797900262466)
			{
				double x = endPoint.X;
				double y = xyz.Y;
				double z = endPoint.Z;
				return new XYZ(x, y, z);
			}
			if (Math.Abs(endPoint.Y - endPoint2.Y) < 0.065616797900262466)
			{
				double x2 = xyz.X;
				double y2 = endPoint.Y;
				double z2 = endPoint.Z;
				return new XYZ(x2, y2, z2);
			}
			if (Math.Abs(endPoint.Y - endPoint2.Y) > 0.065616797900262466 && Math.Abs(endPoint.X - endPoint2.X) > 0.065616797900262466)
			{
				double x3 = xyz.X;
				double y3 = xyz.Y;
				double z3 = endPoint.Z;
				return new XYZ(x3, y3, z3);
			}
			return null;
		}

		public List<Element> GetNoEqualElement(List<Element> lstOne, List<Element> lstTwo)
		{
			List<Element> list = new List<Element>();
			Dictionary<int, Element> dictionary = new Dictionary<int, Element>();
			foreach (Element element in lstTwo)
			{
				dictionary.Add(element.Id.IntegerValue, element);
			}
			foreach (Element element2 in lstOne)
			{
				if (!dictionary.ContainsKey(element2.Id.IntegerValue))
				{
					list.Add(element2);
				}
			}
			return list;
		}

		private ExternalCommandData m_commandData;

		private UIDocument m_uiDoc;

		private Document m_doc;

		private List<BreamInfo> m_lstBreamInfo;

		private const double APPRPEQUAL = 0.065616797900262466;
	}
}
